package com.tanhua.manager.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.manager.mapper.ManagerMapper;
import com.tanhua.manager.pojo.Manager;
import com.tanhua.manager.vo.ManagerVo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Service
public class ManagerService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private ManagerMapper managerMapper;

    //本类的日志对象
    private static final Logger LOGGER = LoggerFactory.getLogger(ManagerService.class);

    private static final String CACHE_KEY_TOKEN_PREFIX = "MANAGER_TOKEN_";

    private static final String CACHE_CODE_PREFIX = "MANAGER_UUID_";

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Value("{jwt.secret}")
    private String secret;

    /**
     * 保存验证码到redis
     *
     * @param uuid
     * @param code
     */
    public void saveVerificationCode(String uuid, String code) {
        try {
            //设置存入验证码的key
            String redisUuidKey = CACHE_CODE_PREFIX + uuid;
            //存入redis中,设置过期时间3分钟
            redisTemplate.opsForValue().set(redisUuidKey, code, Duration.ofMinutes(3));
        } catch (Exception e) {
            LOGGER.error("存储验证码出错", e);
        }
    }

    /**
     * 用户登录
     *
     * @param manager 包含登录的必备信息
     * @return 返回token
     */
    public String login(Manager manager) {
        try {
            //对输入的用户名和密码进行非空判断
            if (StringUtils.isEmpty(manager.getUsername()) || StringUtils.isEmpty(manager.getPassword())) {
                return null;
            }

            //先验证验证码，获取用户上传的uuid
            String uuid = manager.getUuid();
            //去redis中查询
            String redisKey = CACHE_CODE_PREFIX + uuid;
            String value = redisTemplate.opsForValue().get(redisKey);
            //拿redis 中获取的验证码和用户上传的验证码进行比对,先看看验证码过期了没有
            if (StringUtils.isEmpty(value)) {
                return null;//过期了
            } else if (!value.equals(manager.getVerificationCode())) {
                return null;//验证码不正确
            }
            //验证码通过，阅后即焚
            redisTemplate.delete(redisKey);

            //到这里就说明验证码通过,该验证用户名和密码了
            QueryWrapper<Manager> query = new QueryWrapper<>();
            query.eq("username", manager.getUsername())
                    .eq("password", manager.getPassword());
            //这个是从数据库中查到的用户对象
            Manager manager1 = this.managerMapper.selectOne(query);

            //判断
            if (manager1 == null) {
                return null;
            }

            //到这里就说明用户名密码比对通过，登录成功，可以开始制作token令牌了
            HashMap<String, Object> map = new HashMap<>();
            map.put("username", manager1.getUsername());
            map.put("id", manager1.getId());
            //生成token
            String token = Jwts.builder()
                    .setClaims(map)   //设置响应数据体
                    .signWith(SignatureAlgorithm.HS256, secret)  //设置加密方法和加密盐
                    .compact();
            //将token放进redis中,先制作key
            String redisTokenKey = CACHE_KEY_TOKEN_PREFIX + token;
            //在制作value
            String redisTokenValue = MAPPER.writeValueAsString(manager1);
            //存，设置有效时间
            redisTemplate.opsForValue().set(redisTokenKey, redisTokenValue, Duration.ofHours(1));

            //存完返回给前台
            return token;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 查询管理员信息
     *
     * @param token
     * @return
     */
    public ManagerVo queryManagerByToken(String token) {
        try {
            token = token.replace("Bearer ", "");
            String redisTokenKey = CACHE_KEY_TOKEN_PREFIX + token;
            //获取到redis中token的值
            String cacheData = this.redisTemplate.opsForValue().get(redisTokenKey);
            if (StringUtils.isEmpty(cacheData)) {
                return null;
            }

            //刷新时间
            this.redisTemplate.expire(redisTokenKey, 1, TimeUnit.HOURS);
            //将json对象转成user对象
            Manager manager = MAPPER.readValue(cacheData, Manager.class);
            ManagerVo managerVo = new ManagerVo();
            managerVo.setUid(manager.getId());
            managerVo.setUsername(manager.getUsername());
            managerVo.setAvatar(manager.getAvatar());

            return managerVo;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 登出 删除token
     *
     * @param token
     * @return
     */
    public boolean logout(String token) {
        //获取key
        token = token.replace("Bearer ", "");
        String redisTokenKey = CACHE_KEY_TOKEN_PREFIX + token;
        //删除token
        Boolean bool = this.redisTemplate.delete(redisTokenKey);
        return bool;
    }


}
